package com

import com.amazonaws.services.s3.transfer.MyTransferManager
import com.amazonaws.services.s3.transfer.MyTransferManagerBuilder
import com.amazonaws.util.Platform
import com.entity.PackCmd
import com.handler.AuthorityHandler
import com.handler.BucketHandler
import com.handler.InvalidationHandler
import com.handler.PackHandler
import org.slf4j.LoggerFactory
import picocli.CommandLine
import java.io.UnsupportedEncodingException
import java.net.URLDecoder
import java.nio.charset.Charset
import java.nio.file.Files
import java.nio.file.Path
import java.util.*
import kotlin.io.path.*
import kotlin.system.exitProcess

class Main(args: Array<String>) {
    private val dataManage: AwsUtils
    private val commandLine: CommandLine
    private val packCmd: PackCmd

    init {
        this.dataManage = AwsUtils {
            startFiles()
        }
        Config.dataManage = this.dataManage
        this.packCmd = dataManage.packCmd

        commandLine = CommandLine(this.packCmd)

        commandLine.setUseSimplifiedAtFiles(true)
        commandLine.isOptionsCaseInsensitive = true
        commandLine.isSubcommandsCaseInsensitive = true

        //        args = new String[]{"-t", "2", "bname", "one-game"};
//        args = new String[]{"-cls", "-n", "onegame"};
//        args = new String[]{"-r", "D:\\projectPack\\uploadConfig\\test.txt"};
//        args = new String[]{"-cls"};
//        args = new String[]{"-help"};
        commandLine.execute(*args)
    }

    /**
     * 开始执行更新上传
     */
    @OptIn(ExperimentalPathApi::class)
    fun startFiles() {
        // 上传文件配置表
        var configFile: Path? = null
        if (!packCmd.uploadFilePackFile.isNullOrBlank() && Path(packCmd.uploadFilePackFile!!)
                .also { configFile = it }
                .exists()
        ) {
            try {
                val file = configFile!!
                val count = Files.lines(file).use {
                    it.count()
                }
                if (count < 2L) {
                    file.readText().run {
                        commandLine.execute(*this.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray())
                    }
                } else commandLine.execute("@${file.absolutePathString()}")
            } catch (e: Exception) {
                System.err.println("执行配置表有问题, file=${packCmd.uploadFilePackFile} ${e.message}")
            }
            return
        }
        // 如果有更新的文件 需要将他们单独打包到user目录
        if (packCmd.uploadFileList != null) {
            try {
                val files = packCmd.uploadFileList
                var saveFile: Path?
                val newPath = Path(System.getProperty("user.home"), packCmd.bucketName!!)
                if (newPath.exists()) newPath.deleteRecursively()
                newPath.toFile().mkdirs()
                for (i in files!!.indices) {
                    val file = files[i]
                    val tempPath =
                        changeDiskCharacter(file.absolutePath).replace(changeDiskCharacter(packCmd.parentPath!!), "")
                    saveFile = newPath.resolve(tempPath)
                    file.copyTo(saveFile.toFile(), true)
                }
                //   这里将目录弹出来  为了上传失败 可以手动复制传送

                if (Platform.isWindows()) {
                    exec("cmd.exe", "/c", "start", newPath.pathString)
                } else {
                    exec("open", newPath.pathString)
                }
                println("将需要上传的文件打包到临时文件夹，并弹出成功!")
            } catch (e: Exception) {
                System.err.println(
                    "要上传的文件配置表有问题, file=${packCmd.uploadFileList} ${e.message}"
                )
                exitProcess(1)
            }
        }

        if (!packCmd.uploadFileConfig.isNullOrBlank() && Path(packCmd.uploadFileConfig!!).also { configFile = it }
                .exists()) {
            try {
                val file = configFile!!
                val count = Files.lines(file).use {
                    it.count()
                }
                println("执行配置文件 总行数：$count")
                if (count < 2L) {
                    val content = file.readText()
                    commandLine.execute(*content.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray())
                } else commandLine.execute("@${file.absolutePathString()}")
            } catch (e: Exception) {
                System.err.println(
                    "上传文件配置表有问题, file=${packCmd.uploadFileConfig} ${e.message}"
                )
            }
            return
        }

        println("检测 登录用户")
        if (dataManage.checkAccount()) {
            println("error : accessKeyId=" + packCmd.accessKeyId + ", accessKeySecret=" + packCmd.accessKeySecret)
            return
        }

        when (packCmd.type) {
            1 -> PackHandler(myTransferManager)
            2 -> if (!packCmd.bucketName.isNullOrBlank()) BucketHandler(myTransferManager).execute(packCmd.bucketName!!) else println(
                "不能执行创建 = bucketName=" + packCmd.bucketName
            )

            3 -> AuthorityHandler(myTransferManager).execute(packCmd.bucketName!!)
            else -> if (packCmd.uploadFileList != null && packCmd.uploadFileList!!.isNotEmpty()) {
                PackHandler(myTransferManager)
            } else {
                if (!packCmd.clear) println("未指定执行类型")
            }
        }
        // 程序最后执行 清除缓存任务
        println("OY")
        if (packCmd.clear) { // 需要清理
            println("开始清理服务器缓存")
            InvalidationHandler()
        }
    }

    private val myTransferManager: MyTransferManager?
        get() {
            val transferManager = MyTransferManagerBuilder.standard()
                .withS3Client(AwsUtils.awsUtils.s3Client)
                .build()
            println("成功连接AWS S3服务器。。。")
            return transferManager
        }

    /**
     * 执行一个文件
     *
     * @param command 命令
     */
    fun exec(vararg command: String?) {
        val processBuilder = ProcessBuilder(*command)
//        processBuilder.directory(File("cmd"))
        var runningStatus = 0
        var message: String?
        try {
            val process = processBuilder.start()
            val stdInput = process.inputReader()
            val stdError = process.errorReader()
            while ((stdInput.readLine().also { message = it }) != null) {
                if (message!!.length > 3 && (message!!.startsWith("%n%") || message!!.startsWith("%pro%"))) {
                    print("\r")
                    print(message)
                } else {
                    println(message)
                }
            }
            while ((stdError.readLine().also { message = it }) != null) {
                System.err.println(message)
            }
            runningStatus = process.waitFor()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        println(runningStatus)
    }

    /**
     * 转换盘符
     *
     * @param key
     * @return
     */
    fun changeDiskCharacter(key: String): String {
        return key.replace("\\", "/")
    }


    companion object {
        @JvmStatic
        var scanner: Scanner? = null
            get() {
                if (field == null) field = Scanner(System.`in`)
                return field
            }
            private set

        @JvmStatic
        fun main(args: Array<String>) {
            System.setProperty("rootDir", runPath.pathString)

            println(Charset.defaultCharset())
            LoggerFactory.getLogger(Main::class.java).info("启动 -")
            Main(args)

        }

        /**
         * 获取运行路径
         *
         * @return
         */
        @JvmStatic
        val runPath: Path
            get() {
                var file: Path
                val jar = Main::class.java.getResource("Main.class")
                if (jar != null && jar.protocol == "jar") {
                    val url = Main::class.java.protectionDomain.codeSource.location
                    try {
                        var filePath = URLDecoder.decode(url.path, "UTF-8")
//                        println(filePath)
                        if (filePath.endsWith(".jar")) { // 可执行jar包运行的结果里包含".jar"
                            // 截取路径中的jar包名
                            filePath = filePath.substring(0, filePath.lastIndexOf("/") + 1).let {
                                if (filePath.startsWith("/")) {
                                    filePath.substring(1)
                                } else filePath
                            }
                            if (filePath.startsWith("/")) {
                                filePath = filePath.substring(1)
                            }
                        }
//                        println(filePath)
                        file = Path(filePath)
                    } catch (e: UnsupportedEncodingException) {
//			e.printStackTrace();
                        LoggerFactory.getLogger(Main::class.java).error(e.message)
                        file = Path(System.getProperty("user.dir"))
                    }
                } else {
                    file = Path(System.getProperty("user.dir"))
                }
                return if (file.pathString.endsWith(".jar"))
                    file.parent
                else file
            }
    }
}

fun isNumeric(str: String): Boolean {
    return str.matches(Regex("[0-9]+"))
}